#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "elog.h"


#define LOG_EVT_OUTPUT  (1 << 0)


extern void elog_port_output(const char *log, size_t size);


static TaskHandle_t elog_task_handle;


static void elog_task_handler(void *arg)
{
    char log_buff[ELOG_LINE_BUF_SIZE];
    size_t log_size;
    uint32_t notif_bits;
    for (;;)
    {
        xTaskNotifyWait(0, 0xffffffff, &notif_bits, portMAX_DELAY);

        while (true)
        {
            log_size = elog_async_get_log(log_buff, ELOG_LINE_BUF_SIZE);

            if (log_size)
                elog_port_output(log_buff, log_size);
            else
                break;
        }
    }
}

static void elog_lowlevel_init(void)
{
    elog_init();

    elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);
    elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME | ELOG_FMT_P_INFO);
    elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME | ELOG_FMT_P_INFO);
    elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_TAG);

    elog_start();
}

void app_logger_init(void)
{
    elog_lowlevel_init();

    xTaskCreate(elog_task_handler, "log", 512, NULL, 1, &elog_task_handle);
    configASSERT(elog_task_handle);
}

void elog_async_output_notice(void)
{
    CHECK_RET(elog_task_handle);

    if (is_user())
    {
        xTaskNotify(elog_task_handle, LOG_EVT_OUTPUT, eSetBits);
    }
    else
    {
        BaseType_t xHigherPriorityTaskWoken;
        xTaskNotifyFromISR(elog_task_handle, LOG_EVT_OUTPUT, eSetBits, &xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
}
